<template>
  <a-spin :spinning="loading">
    <section class="flex items-center justify-between mb-16">
      <section class="flex items-center">
        <span class="label">角色名：</span>
        <a-input
          @keyup.enter="search"
          class="w-300"
          allow-clear
          placeholder="请输入角色名"
          :max-length="100"
          v-model="searchInp"
        />
        <a-button class="mx-8" type="primary" @click="search">查询</a-button>
        <a-button @click="reset">重置</a-button>
      </section>
      <a-button v-if="$permissionJudge('RoleCreate')" @click="showRoleInfoModal = true" type="primary" icon="plus"
        >新建</a-button
      >
    </section>
    <a-table row-key="id" :columns="columns" :data-source="data" :pagination="pagination">
      <template #description="description">
        <a-tooltip :title="description"
          ><section class="overflow">{{ description }}</section></a-tooltip
        >
      </template>
      <template #action="val, data, index">
        <template v-if="$permissionJudge('RoleUpdate')">
          <a
            @click.stop="editRole(data)"
            :class="{
              gray: data.isSystemRole,
              'cursor-not-allowed': data.isSystemRole,
            }"
            href="javascript:;"
            >编辑信息</a
          >
          <a-divider type="vertical" />
          <a
            v-if="$permissionJudge('PowerUpdate')"
            @click.stop="editPermission(data)"
            :class="{
              gray: data.isSystemRole,
              'cursor-not-allowed': data.isSystemRole,
            }"
            href="javascript:;"
            >权限变更</a
          >
        </template>
        <a-divider v-if="$permissionJudge('RoleDelete') && $permissionJudge('RoleUpdate')" type="vertical" />
        <a
          v-if="$permissionJudge('RoleDelete')"
          @click.stop="deleteRole(data, index)"
          :class="{
            gray: data.isSystemRole,
            red: !data.isSystemRole,
            'cursor-not-allowed': data.isSystemRole,
          }"
          href="javascript:;"
          >删除</a
        >
      </template>
    </a-table>
    <a-modal
      :title="isEdit ? '修改角色信息' : '新建角色'"
      v-model="showRoleInfoModal"
      :confirm-loading="confirmLoading"
      @cancel="cancel"
      @ok="confirmRole"
    >
      <a-form :form="roleForm">
        <a-form-item label="角色名">
          <a-input
            placeholder="请输入角色名"
            :max-length="30"
            v-decorator="['name', { rules: [{ required: true, message: '请输入角色名', whitespace: true }] }]"
          />
          <a-input type="hidden" v-decorator="['id']" />
        </a-form-item>
        <a-form-item label="角色描述">
          <a-textarea
            placeholder="请输入角色描述"
            :max-length="300"
            :rows="3"
            v-decorator="['description', { initialValue: '' }]"
          />
        </a-form-item>
      </a-form>
    </a-modal>
    <a-modal
      title="变更角色权限"
      width="1000px"
      v-model="showPermissionModal"
      :confirm-loading="confirmLoading"
      @cancel="showPermissionModal = false"
      @ok="updateRolePermission"
    >
      <section style="max-height: 600px" class="overflow-auto">
        <section v-for="menu in permissionData" :key="menu.key">
          <section class="text-16 mb-16">{{ menu.title }}</section>
          <section class="checkbox-group">
            <a-checkbox
              class="mb-8"
              :indeterminate="checkIndeterminate(menu)"
              :checked="checkAll(menu)"
              @click="toggleCheckAll(menu)"
              >全选</a-checkbox
            >
            <a-checkbox class="mb-8" :checked="permissionIds.includes(menu.key)" @click="toggleChecked(menu.key)"
              >菜单</a-checkbox
            >
            <a-checkbox
              class="mb-8"
              v-for="btn in menu.children"
              :key="btn.key"
              :checked="permissionIds.includes(btn.key)"
              @click="toggleChecked(btn.key)"
              >{{ btn.title }}</a-checkbox
            >
          </section>
          <ADivider class="my-8" />
        </section>
        <!--<a-tree-->
        <!--v-model="permissionIds"-->
        <!--checkable-->
        <!--:expanded-keys.sync="expandedKeys"-->
        <!--:tree-data="permissionData"-->
        <!--@check="checkPermission"-->
        <!--/>-->
      </section>
    </a-modal>
  </a-spin>
</template>
<script>
import {
  getRoleList,
  editRoleBaseInfo,
  createRole,
  deleteRole,
  getPermissionList,
  getRolePermission,
  updateRolePermission,
} from '@/api/role'
import { tableMixins } from '@/utils/mixins'

export default {
  name: 'RolesManage',
  mixins: [tableMixins],
  data() {
    return {
      isEdit: false,
      loading: false,
      confirmLoading: false,
      showRoleInfoModal: false,
      showPermissionModal: false,
      id: '',
      searchInp: '',
      roleForm: this.$form.createForm(this),
      columns: [
        { dataIndex: 'name', title: '角色名' },
        {
          dataIndex: 'description',
          width: '30%',
          ellipsis: true,
          title: '角色描述',
          scopedSlots: { customRender: 'description' },
        },
        { dataIndex: 'createTime', title: '创建时间' },
        { dataIndex: 'updateTime', title: '最后修改时间' },
        { dataIndex: 'action', width: 220, align: 'center', title: '操作', scopedSlots: { customRender: 'action' } },
      ],
      data: [],
      permissionIds: [],
      expandedKeys: [],
      permissionData: [],
    }
  },
  created() {
    this.$watch('showPermissionModal', (val) => {
      val && this.getPermissionList()
    })
    this.getData()
  },
  methods: {
    getData() {
      this.loading = true
      getRoleList({
        name: this.searchInp.trim(),
        pageNo: this.pageNum,
        pageSize: this.rowsNum,
      })
        .then((res) => {
          this.data = res.items
          this.total = res.rowCount
        })
        .finally(() => (this.loading = false))
    },
    editRole(data) {
      if (data.isSystemRole) return
      this.isEdit = true
      this.showRoleInfoModal = true
      this.$nextTick(() => {
        this.roleForm.setFieldsValue(data)
      })
    },
    editPermission(data) {
      if (data.isSystemRole) return
      this.showPermissionModal = true
      this.id = data.id
      getRolePermission(data.id).then((data) => {
        this.permissionIds = data.permissionIds
      })
    },
    checkIndeterminate(menu) {
      const currRouteAllPermissionIds = [menu.key, ...menu.children.map((e) => e.key)]
      const permissionIds = this.permissionIds
      if (currRouteAllPermissionIds.every((e) => permissionIds.includes(e))) return false
      else return currRouteAllPermissionIds.some((e) => permissionIds.includes(e)) && permissionIds.length > 0
    },
    checkAll(menu) {
      const currRouteAllPermissionIds = [menu.key, ...menu.children.map((e) => e.key)]
      const permissionIds = this.permissionIds
      return currRouteAllPermissionIds.every((e) => permissionIds.includes(e)) && permissionIds.length > 0
    },
    toggleCheckAll(menu) {
      const currRouteAllPermissionIds = [menu.key, ...menu.children.map((e) => e.key)]
      if (this.checkAll(menu))
        this.permissionIds = this.permissionIds.filter((e) => !currRouteAllPermissionIds.includes(e))
      else
        currRouteAllPermissionIds.forEach((key) => {
          if (this.permissionIds.includes(key)) return
          this.permissionIds.push(key)
        })
    },
    toggleChecked(permissionItemKye) {
      if (this.permissionIds.includes(permissionItemKye))
        this.permissionIds = this.permissionIds.filter((e) => e !== permissionItemKye)
      else this.permissionIds.push(permissionItemKye)
    },
    deleteRole(data, index) {
      if (data.isSystemRole) return
      this.$confirm({
        title: '请确认删除角色信息',
        content:
          '请确认是否删除角色信息？删除该角色后，相应被赋予该角色的用户将失去对应的权限。请问您确认删除角色信息吗？',
        okText: '确定',
        okType: 'danger',
        cancelText: '取消',
        onOk: () => {
          this.loading = true
          deleteRole({ id: data.id })
            .then(() => {
              this.$message.success('删除成功！')
              this.data.splice(index, 1)
              if (this.data.length === 0 && this.pageNum > 1) this.pageNum--
              this.getData()
            })
            .finally(() => (this.loading = false))
        },
      })
    },
    getPermissionList() {
      getPermissionList().then((data) => {
        this.expandedKeys = []
        const permissionsList = data.permissionsList[0].permissionsDtos
        this.mapPermissionData(permissionsList)
        this.permissionData = permissionsList
      })
    },
    cancel() {
      this.showRoleInfoModal = false
      this.isEdit = false
      this.roleForm.resetFields()
    },
    confirmRole() {
      this.roleForm.validateFields((err, values) => {
        if (!err) {
          const confirmFn = this.isEdit ? editRoleBaseInfo : createRole
          this.confirmLoading = true
          confirmFn(this.$utils.trimValue(values))
            .then(() => {
              this.$message.success(`${this.isEdit ? '修改' : '新增'}成功！`)
              this.cancel()
              this.getData()
            })
            .finally(() => (this.confirmLoading = false))
        }
      })
    },
    updateRolePermission() {
      this.confirmLoading = true
      if (this.permissionIds.checked) this.permissionIds = this.permissionIds.checked
      updateRolePermission({ id: this.id, permissionIds: this.permissionIds })
        .then(() => {
          this.$message.success('变更角色权限成功')
          this.getData()
          this.showPermissionModal = false
        })
        .finally(() => (this.confirmLoading = false))
    },
    mapPermissionData(data) {
      data.forEach((item) => {
        item.title = item.permissionName
        item.key = item.permissionId
        item.selectable = false
        item.children = item.permissionsDtos
        this.expandedKeys.push(item.key)
        if (item.children && item.children.length > 0) this.mapPermissionData(item.children)
      })
    },
    search() {
      this.pageNum = 1
      this.getData()
    },
    reset() {
      this.pageNum = 1
      this.searchInp = ''
      this.getData()
    },
  },
}
</script>

<style scoped>
.red {
  color: red;
}

.gray {
  color: #999;
}
</style>
